package _binary_tree

import common.TreeNode
import org.junit.Assert
import org.junit.Test

/**
https://leetcode.cn/problems/leaf-similar-trees/description

题型：二叉树的任何一种遍历方式。 答案中，使用的是后序遍历。

```
872. 叶子相似的树
请考虑一棵二叉树上所有的叶子，这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。
举个例子，如上图所示，给定一棵叶值序列为 (6, 7, 4, 9, 8) 的树。
如果有两棵二叉树的叶值序列是相同，那么我们就认为它们是 叶相似 的。
如果给定的两个根结点分别为 root1 和 root2 的树是叶相似的，则返回 true；否则返回 false 。

示例 1：
输入：root1 = [3,5,1,6,2,9,8,null,null,7,4], root2 = [3,5,1,6,7,4,2,null,null,null,null,null,null,9,8]
输出：true

示例 2：
输入：root1 = [1,2,3], root2 = [1,3,2]
输出：false

提示：
给定的两棵树结点数在 [1, 200] 范围内
给定的两棵树上的值在 [0, 200] 范围内
```
 */
class leetcode_872 {
    @Test
    fun test_1() {
        var root1: TreeNode? = null
        run {
            val n3 = TreeNode(3)
            val n5 = TreeNode(5)
            val n1 = TreeNode(1)
            n3.left = n5
            n3.right = n1

            val n6 = TreeNode(6)
            val n2 = TreeNode(2)
            val n9 = TreeNode(9)
            val n8 = TreeNode(8)
            n5.left = n6
            n5.right = n2
            n1.left = n9
            n1.right = n8

            val n7 = TreeNode(7)
            val n4 = TreeNode(4)
            n2.left = n7
            n2.right = n4
            root1 = n3
        }

        var root2: TreeNode? = null
        run {
            val n3 = TreeNode(3)
            val n5 = TreeNode(5)
            val n1 = TreeNode(1)
            n3.left = n5
            n3.right = n1

            val n6 = TreeNode(6)
            val n7 = TreeNode(7)
            val n4 = TreeNode(4)
            val n2 = TreeNode(2)
            n5.left = n6
            n5.right = n7
            n1.left = n4
            n1.right = n2

            val n9 = TreeNode(9)
            val n8 = TreeNode(8)
            n2.left = n9
            n2.right = n8
            root2 = n3
        }

        val actual = leafSimilar(root1, root2)
        val expected = true
        Assert.assertEquals(expected, actual)
    }

    @Test
    fun test_2() {
        val root1: TreeNode = TreeNode(1)
        root1.left = TreeNode(2)
        root1.right = TreeNode(3)

        val root2: TreeNode = TreeNode(1)
        root2.left = TreeNode(3)
        root2.right = TreeNode(2)

        val actual = leafSimilar(root1, root2)
        val expected = false
        Assert.assertEquals(expected, actual)
    }

    private fun leafSimilar(root1: TreeNode?, root2: TreeNode?): Boolean {
        /**
        题型：二叉树的任何一种遍历方式。 答案中，使用的是后序遍历。
        思路：收集两棵树的叶子节点到list，判断list 1 和 list2 的大小与元素是否相同？
        若大小相同，且元素相同，说明两棵树的叶值序列相同。
         */
        val list1: ArrayList<Int> = ArrayList()
        val list2: ArrayList<Int> = ArrayList()
        f(root1, list1)
        f(root2, list2)
        return list1.size == list2.size && list1.toString() == list2.toString()
    }

    private fun f(root: TreeNode?, list: ArrayList<Int>) {
        // 1 确定函数参数以及返回值
        // 2 确定终止条件
        if (root == null) {
            return
        }
        // 3 确定单层递归的遍历逻辑：后序遍历
        // 左
        f(root.left, list)

        // 右
        f(root.right, list)

        // 中
        if (root.left == null && root.right == null) {
            list.add(root.`val`)
        }
    }
}